package com.minelx.woods.server.entity;

import com.minelx.woods.server.entity.values.ReviewValues;
import com.mongodb.client.MongoCollection;
import org.bson.Document;
import org.bson.types.ObjectId;

import java.util.List;
import java.util.Objects;

public class Review {

	private final MongoCollection<Document> reviewsCollection;

	private final String id;

	public Review(MongoCollection<Document> reviewsCollection, String id) {
		this.reviewsCollection = reviewsCollection;
		this.id = id;
	}

	public boolean approve(String reviewerId) {
		ReviewValues review = values();
		if (!review.canApprovedBy(reviewerId)) {
			throw new UnsupportedOperationException("can't do approving.");
		}
		// add reviewerId to approved reviewer set
		reviewsCollection.updateOne(self(), new Document("$addToSet", new Document("approved", reviewerId)));
		return review.remainsLastReviewer();
	}

	public void reject(String reviewerId) {
		if (!values().canRejectedBy(reviewerId)) {
			throw new UnsupportedOperationException("can't do rejection.");
		}
		// mark as rejected
		reviewsCollection.updateOne(self(), new Document("$set", new Document("isRejected", true)));
	}

	public ReviewValues values() {
		// throw if the id can't be found
		Document document = Objects.requireNonNull(reviewsCollection.find(self()).first());
		return new ReviewValues(id,
				document.getString("name"),
				document.getString("taskId"),
				document.getString("submitterId"),
				((List<String>) document.get("approved", List.class)),
				((List<String>) document.get("reviewers", List.class)),
				document.getBoolean("isRejected"));
	}

	private Document self() {
		return new Document("_id", new ObjectId(id));
	}
}
